package be.lreenaers.mirr0r.components;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;

import org.jdom.Document;

import be.lreenaers.mirr0r.components.utils.CsvFileFilter;
import be.lreenaers.mirr0r.components.utils.Utils;
import be.lreenaers.mirr0r.schema.components.GenericDocument;
import be.lreenaers.mirr0r.schema.components.SimpleDublinCore.DCDocument;

import com.csvreader.CsvReader;

/**
 * Mirror converter's main GUI component. it extends JPanel and implements
 * ActionListener.
 * 
 * @author Ludovic Reenaers
 * @version 1.1
 * @since beta
 * 
 */
@SuppressWarnings("serial")
public class Converter extends JPanel implements ActionListener {
	/**
	 * Mirror converter's main GUI component. it extends JPanel and implements
	 * ActionListener.
	 * 
	 * @see JPanel
	 * @see ActionListener
	 * @since beta
	 */
	static private final String newline = "\n";
	private JButton openButton, saveButton, writeButton, addAssocButton,
			addSchButton;
	private JPanel buttonPanel;
	private ImageIcon xmlIcon, addAssocButtonIcon, addSchButtonIcon,
			openButtonIcon, saveButtonIcon, genButtonIcon;
	private JScrollPane logScrollPane;
	protected JTextArea log;
	private JFileChooser fc;
	protected JTabbedPaneWithCloseIcons tabbedPane;

	private CsvReader reader;
	//private SchemaManager schManager;

	private String saveDirectoryPath;
	private String sourcePath;

	private int selectedTabIndex;
	
	private ArrayList<GenericDocument> docs = new ArrayList<GenericDocument>();

	/**
	 * Only available constructor, uses ResourceBundle to initialize
	 * application's main panel.
	 * 
	 * @since beta
	 */
	public Converter() {
		super(new BorderLayout());
		this.initiateDefaultValues();
		this.setUpComponents();
	}

	private void setUpComponents() {
		this.createLogger();
		fc = new JFileChooser();
		this.createIcons();
		this.createPanels();
		this.createButtons();
		this.setUpPanels();
	}

	private void setUpPanels() {
		add(buttonPanel, BorderLayout.PAGE_START);
		add(this.tabbedPane, BorderLayout.CENTER);
		add(logScrollPane, BorderLayout.PAGE_END);
		this.setPreferredSize(new Dimension(800, 600));
	}

	protected void setSelectedTabIndex(int index) {
		this.selectedTabIndex = index;
	}

	private void createButtons() {
		addSchButton = new JButton(addSchButtonIcon);
		addSchButton.setToolTipText(Utils.getTranslator().getString("addSch"));
		addSchButton.setMargin(Utils.noInsets);
		addSchButton.setEnabled(false);
		addSchButton.addActionListener(this);

		addAssocButton = new JButton(addAssocButtonIcon);
		addAssocButton.setToolTipText(Utils.getTranslator().getString("addAssoc"));
		addAssocButton.setMargin(Utils.noInsets);
		addAssocButton.setEnabled(false);
		addAssocButton.addActionListener(this);

		openButton = new JButton(openButtonIcon);
		openButton.setToolTipText(Utils.getTranslator().getString("openSourceFile"));
		openButton.setMargin(Utils.noInsets);
		openButton.addActionListener(this);

		saveButton = new JButton(saveButtonIcon);
		saveButton.setToolTipText(Utils.getTranslator().getString("saveToDirectory"));
		saveButton.setMargin(Utils.noInsets);
		saveButton.addActionListener(this);

		writeButton = new JButton(genButtonIcon);
		writeButton.setToolTipText(Utils.getTranslator().getString("generate"));
		writeButton.setMargin(Utils.noInsets);
		writeButton.setEnabled(false);
		writeButton.addActionListener(this);

		buttonPanel.add(openButton);
		buttonPanel.add(saveButton);
		buttonPanel.add(addAssocButton);
		buttonPanel.add(addSchButton);
		buttonPanel.add(writeButton);
	}

	private void createPanels() {
		buttonPanel = new JPanel();
		tabbedPane = new JTabbedPaneWithCloseIcons();
		tabbedPane.setParent(this);
		tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
		tabbedPane.addChangeListener(new TabbedPaneListener(this));
	}

	private void addATab(String label, JComponent panel) {
		tabbedPane.addTab(label, panel, xmlIcon);
	}

	private void createLogger() {
		log = new JTextArea(5, 20);
		log.setMargin(new Insets(5, 5, 5, 5));
		log.setEditable(false);
		logScrollPane = new JScrollPane(log);
	}

	private void createIcons() {
		xmlIcon = Utils.createImageIcon("img/xml16x16.png");
		addAssocButtonIcon = Utils.createImageIcon("img/mapper32X32.png");
		addSchButtonIcon = Utils.createImageIcon("img/csvxml.jpg");
		openButtonIcon = Utils.createImageIcon("img/open.png");
		saveButtonIcon = Utils.createImageIcon("img/save.png");
		genButtonIcon = Utils.createImageIcon("img/generate.png");
	}

	private void initiateDefaultValues() {
		saveDirectoryPath = "";

	}

	protected void log(String info) {
		log.append(info);
		log.setCaretPosition(log.getDocument().getLength());
	}

	/**
	 * Inherited from ActionListener, this methods handles components related
	 * actions performed within the application.
	 * 
	 * @param e
	 *            The event itself.
	 * @see ActionListener
	 * @see ActionEvent
	 * @since beta
	 */
	public void actionPerformed(ActionEvent e) {

		if (e.getSource() == openButton) {
			if (this.tabbedPane.getTabCount() > 0) {
				this.tabbedPane.removeAll();
			}
			try {
				if (this.selectSourceFile()) {
					this.addAssocButton.setEnabled(true);
					this.writeButton.setEnabled(true);
					this.addSchButton.setEnabled(true);
					this.buildPanels();
				}
			} catch (IOException e1) {
				this.log(Utils.getTranslator().getString("noSourceFile"));
			}

		} else if (e.getSource() == saveButton) {
			this.selectTargetDirectory();
		} else if (e.getSource() == addSchButton) {

		} else if (e.getSource() == addAssocButton) {

			this.tabbedPane.validate();
		} else if (e.getSource() == writeButton) {
			try {
				this.writeDown();
			} catch (IOException e1) {
				this.log(Utils.getTranslator().getString("noSourceFile"));
			} 
		}
		
	}



	protected JPanel getActiveTabPanel() {
		JScrollPane scroll = (JScrollPane) this.tabbedPane
				.getComponentAt(this.selectedTabIndex);
		JPanel panel = (JPanel) scroll.getViewport().getComponent(0);
		return panel;
	}

	private void selectTargetDirectory() {
		fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		int returnVal = fc.showSaveDialog(Converter.this);
		if (returnVal == JFileChooser.APPROVE_OPTION) {
			File file = fc.getSelectedFile();
			this.saveDirectoryPath = file.getPath();
		} else {
			this.log(Utils.getTranslator().getString("saveCanceled") + newline);
		}
	}

	private boolean selectSourceFile() throws IOException {
		fc.setFileFilter(new CsvFileFilter(Utils.getTranslator().getString("CsvOnly")));
		int returnVal = fc.showOpenDialog(Converter.this);
		if (returnVal == JFileChooser.APPROVE_OPTION) {
			this.getSourceFile();
			return true;
		} else {
			this.log(Utils.getTranslator().getString("openCanceled") + newline);
			return false;
		}
	}

	private void getSourceFile() throws IOException {
		this.sourcePath = fc.getSelectedFile().getPath();
		this.setReader();
		String[] csvColNames = this.reader.getHeaders();
		Utils.setColumnList(csvColNames);
		
		if (csvColNames.length<=0){
			this.log(Utils.getTranslator().getString("noHeaders"));
		}
	}

	private void setReader() throws FileNotFoundException, IOException {
		this.reader = new CsvReader(this.sourcePath);
		this.reader.readHeaders();
	}
	private void serializeDoc(GenericDocument doc) throws IOException{
		this.setReader();
		Utils.writeFile((Document)doc.getXml(this.reader),this.saveDirectoryPath, doc.getName());
		
	}
	private void writeDown() throws IOException{
		Iterator<GenericDocument> iter = this.docs.iterator();
		while (iter.hasNext()){
			this.serializeDoc(iter.next());
		}
	}

	private void buildPanels(){
		DCDocument doc = new DCDocument();
		this.docs.add(doc);
		this.addATab(doc.getName(),doc.getSwing());
	}
	
}
